﻿using System;
using System.Drawing;
using System.Windows.Forms;
using SharpDX.Windows;

namespace Ensemble_Windows.Core
{
    /// <summary>
    ///     渲染基类
    /// </summary>
    public abstract class Direct
    {
        private readonly Time _clock = new Time();

        /// <summary>
        ///     window控件承载
        /// </summary>
        public Form Form { get; set; }

        private FormWindowState CurrentFormWindowState { get; set; }
        private bool Disposed { get; set; }
        private float FrameAccumlator { get; set; }
        private int FrameCount { get; set; }
        private Configuration Configuration { get; set; }

        /// <summary>
        ///     返回句柄显示
        /// </summary>
        protected IntPtr DisplayHandle
        {
            get { return Form.Handle; }
        }

        /// <summary>
        ///     获取配置
        /// </summary>
        public Configuration Config
        {
            get { return Configuration; }
        }

        /// <summary>
        ///     获取上次帧后传递的秒数
        /// </summary>
        public float FrameDelta { get; private set; }

        /// <summary>
        ///     获取上次帧后传递的秒数
        /// </summary>
        public float FramePerSecond { get; private set; }

        ~Direct()
        {
            if (Disposed) return;
            Dispose(false);
            Disposed = true;
        }

        /// <summary>
        ///     释放资源
        /// </summary>
        public void Dispose()
        {
            if (!Disposed)
            {
                Dispose(true);
                Disposed = true;
            }
            GC.SuppressFinalize(this);
        }

        /// <summary>
        ///     释放资源
        /// </summary>
        /// <param name="disposeManagedResources">释放管理的资源</param>
        protected virtual void Dispose(bool disposeManagedResources)
        {
            if (disposeManagedResources)
                if (Form != null)
                    Form.Dispose();
        }

        /// <summary>
        ///     创建窗体
        /// </summary>
        /// <param name="config">配置</param>
        /// <returns>渲染窗体</returns>
        protected virtual Form CreateForm(Configuration config)
        {
            return new RenderForm(config.Title)
            {
                ClientSize = new Size(config.Width, config.Height)
            };
        }

        /// <summary>
        ///     运行窗体
        /// </summary>
        public void Run()
        {
            Run(new Configuration());
        }

        /// <summary>
        ///     运行窗体
        /// </summary>
        /// <param name="configuration">配置</param>
        public void Run(Configuration configuration)
        {
            Configuration = configuration ?? new Configuration();
            Form = CreateForm(Configuration);
            Initialize(configuration);

            var isFormClosed = false;
            var formIsResizeing = false;

            Form.MouseClick += HandleMouseClick;
            Form.KeyDown += HandleKeyDown;
            Form.FormBorderStyle = FormBorderStyle.FixedDialog;
            Form.MaximizeBox = false;
            //_form.Icon = new System.Drawing.Icon("favicon.ico");
            Form.KeyUp += HandleKeyUp;
            Form.Resize += (o, args) =>
            {
                if (Form.WindowState != CurrentFormWindowState)
                    HandleResize();

                CurrentFormWindowState = Form.WindowState;
            };

            Form.ResizeBegin += (o, args) => { formIsResizeing = true; };
            Form.ResizeEnd += (o, args) =>
            {
                formIsResizeing = false;
                HandleResize();
            };

            Form.Closed += (o, args) => { isFormClosed = true; };

            LoadContent();
            _clock.Start();
            BeginRun();
            RenderLoop.Run(Form, () =>
            {
                if (isFormClosed)
                    return;

                OnUpdate();
                if (!formIsResizeing)
                    Render();
            });

            UnloadContent();
            EndRun();
        }

        /// <summary>
        ///     游戏初始化
        /// </summary>
        /// <param name="configuration">配置</param>
        protected abstract void Initialize(Configuration configuration);

        /// <summary>
        ///     加载资源
        /// </summary>
        protected virtual void LoadContent()
        {
        }

        /// <summary>
        ///     卸载资源
        /// </summary>
        protected virtual void UnloadContent()
        {
        }

        /// <summary>
        ///     游戏更新
        /// </summary>
        /// <param name="time">更新频率</param>
        protected virtual void Update(Time time)
        {
            GC.Collect();
        }

        /// <summary>
        ///     鼠标点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleMouseClick(object sender, MouseEventArgs e)
        {
            MouseClick(e);
        }

        /// <summary>
        ///     按键按下事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleKeyDown(object sender, KeyEventArgs e)
        {
            KeyDown(e);
        }

        /// <summary>
        ///     按键弹起事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleKeyUp(object sender, KeyEventArgs e)
        {
            KeyUp(e);
        }

        /// <summary>
        ///     窗体拖动事件
        /// </summary>
        private void HandleResize()
        {
        }

        /// <summary>
        ///     鼠标点击
        /// </summary>
        /// <param name="e"></param>
        protected virtual void MouseClick(MouseEventArgs e)
        {
        }

        /// <summary>
        ///     按键按下
        /// </summary>
        /// <param name="e"></param>
        protected virtual void KeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
                Exit();
        }

        /// <summary>
        ///     按键弹起
        /// </summary>
        /// <param name="e"></param>
        protected virtual void KeyUp(KeyEventArgs e)
        {
        }

        /// <summary>
        ///     游戏开始运行
        /// </summary>
        protected virtual void BeginRun()
        {
        }

        /// <summary>
        ///     游戏结束运行
        /// </summary>
        protected virtual void EndRun()
        {
        }

        /// <summary>
        ///     关闭窗体
        /// </summary>
        public void Exit()
        {
            Form.Close();
        }

        private void OnUpdate()
        {
            FrameDelta = (float) _clock.Update();
            Update(_clock);
        }

        private void Render()
        {
            FrameAccumlator += FrameDelta;
            ++FrameCount;
            if (FrameAccumlator >= 1.0f)
            {
                FramePerSecond = FrameCount / FrameAccumlator;

                Form.Text = Configuration.Title;
                FrameAccumlator = 0.0f;
                FrameCount = 0;
            }

            BeginDraw();
            Draw(_clock);
            EndDraw();
        }

        /// <summary>
        ///     绘图
        /// </summary>
        /// <param name="time">绘图频率</param>
        protected virtual void Draw(Time time)
        {
        }

        /// <summary>
        ///     开始绘图
        /// </summary>
        protected virtual void BeginDraw()
        {
        }

        /// <summary>
        ///     结束绘图
        /// </summary>
        protected virtual void EndDraw()
        {
        }
    }
}